package com.jzcn.common.base;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzcn.common.exceptions.BusinessException;
import com.jzcn.common.response.ResponseCode;
import org.apache.ibatis.annotations.Mapper;


import java.lang.reflect.InvocationTargetException;
import java.util.List;

/**
 * @author peng.l
 * @version 0.0.1
 * @date 2020/10/19 1:04
 */
@Mapper
public class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseDomain> extends ServiceImpl<M, T> implements IBaseService<T> {

    /**
     * 通过反射调用 getId()
     */
    private static final String INVOKE_ID = "getId";

    /**
     * 通过反射调用 getState()
     */
    private static final String INVOKE_State = "getState";

    /**
     * 通过反射调用 getIsDelete()
     */
    private static final String INVOKE_Delete = "getIsDelete";

    /**
     * 检查字段：ID
     */
    protected static final String ID = "id";

    @Override
    public boolean create(T domain) {
        return super.save(domain);
    }

    @Override
    public boolean remove(Integer id) {
        if (checkId(id)) {
            return super.removeById(id);
        }
        return false;
    }

    @Override
    public boolean update(T domain) {
        try {
            if (checkId((Integer) domain.getClass().getMethod(INVOKE_ID).invoke(domain))) {
                return super.updateById(domain);
            }
            return false;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage());
        }
    }

    @Override
    public T get(Integer id) {
        T domain = super.getById(id);
        if (null == domain) {
            throw new BusinessException(ResponseCode.RESULT_DATA_NONE);
        }
        return domain;
    }

    @Override
    public List<T> list(Wrapper<T> queryWrapper){
        try{
            return super.list(queryWrapper);
        }catch (Exception e){
            throw  new BusinessException(e.getMessage());
        }

    }

    @Override
    public IPage<?> page(int current, int size, T domain) {
        Page<T> page = new Page<>(current, size);
        LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
        return super.page(page, wrapper);
    }

    /**
     * 检查 ID 是否存在
     *
     * @param id {@code Long} ID
     * @return {@code boolean} ID 不存在则抛出异常
     */
    protected boolean checkId(Integer id) {
        if (!checkUniqueness(ID, id)) {
            throw new BusinessException(ResponseCode.RESULT_DATA_NONE);
        }
        return true;
    }

    /**
     * 检查某个字段是否存在
     *
     * @param column 字段名
     * @param value  值
     * @return
     */
    protected boolean checkUniqueness(String column, Object value) {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        wrapper.eq(column, value);
        return super.count(wrapper) > 0;
    }

    /**
     * 检查某个字段除了本体还是否存在
     *
     * @param column 字段名
     * @param value  值
     * @return
     */
    protected boolean checkUpdateUniqueness(T domain, String column, Object value) {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        wrapper.eq(column, value);
        try {
            wrapper.ne(ID, domain.getClass().getMethod(INVOKE_ID).invoke(domain));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return super.count(wrapper) > 0;
    }
}
